
package org.japril.jutil.uri;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *   Base class for objects that know how to fetch the 
 *   {@link InputStream} to read the resource a URI locate.
 * </p>
 * @author Arne Halvorsen (AH)
 */
public abstract class UriInputStreamFetcher  
{
  private final String m_scheme;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param name {@link #getScheme()}.
   */
  protected UriInputStreamFetcher(String name){ m_scheme=name; }
  
  /**
   * <p>
   *   Gets scheme {@code this} understand.
   * </p>
   * @return Schema.
   */
  public final String getScheme(){ return m_scheme; }
  
  /**
   * <p>
   *   Fetch resource.
   * </p>
   * @param uri {@link URI} to fetch from.
   * @return Resource or {@code null} if does not exists physical in this world.
   * @throws IOException If fails.
   */
  protected abstract InputStream fetch_(URI uri) throws IOException;
  
  private static final Map<String, UriInputStreamFetcher> m_fetchers=
    new HashMap<String, UriInputStreamFetcher>();
  
  private static void addFetcher(UriInputStreamFetcher f)
  {
    m_fetchers.put(f.getScheme(), f);  
  }
  
  static 
  {
    addFetcher(new HttpUriFetcher());
    addFetcher(new JavaObjectUriFetcher());
  }
  
  /**
   * <p>
   *   Fetch resource.
   * </p>
   * @param uri {@link URI} to fetch from.
   * @return Resource or {@code null} if does not exists physical in this world.
   * @throws IOException If fails.
   */
  public static InputStream fetch(String uri) throws IOException
  {
    if (uri==null)
    {
      throw new NullPointerException("uri");
    }
    
    try
    {
      return fetch(new URI(uri));
    }
    catch (URISyntaxException urisx)
    {
      throw new IllegalArgumentException(uri);
    }
  }
  
  /**
   * <p>
   *   Fetch
   *   {@link InputStream}.
   * </p>
   * @param uri {@link URI} to fetch for.
   * @return Stream or {@code null} if does not exists physical in this world.
   * @throws IOException If fails.
   */
  public static InputStream fetch(URI uri) throws IOException
  {
    if (uri==null)
    {
      throw new NullPointerException("uri");
    }
    
    String scheme=uri.getScheme();
    UriInputStreamFetcher fetcher=m_fetchers.get(scheme);
    return fetcher==null ? null : fetcher.fetch_(uri);
  }
  
  public static void main(String[] args) 
  {
    try
    {
      System.out.println("---- an java object ----");
      
      InputStream is1=fetch("java-object:org.japril.jutil.uri.AnObject");
      ObjectInputStream ois=new ObjectInputStream(is1);
      Object o=ois.readObject();
      System.out.println(o);
      ois.close();
      
      System.out.println("---- an url ----");
      
      InputStream is2=fetch("http://www.dagbladet.no/tegneserie/");
      InputStreamReader isr=new InputStreamReader(is2);
      BufferedReader br=new BufferedReader(isr);
      String line=br.readLine();
      while (line!=null)
      {
        System.out.println(line);
        line=br.readLine();
      }
      br.close();
    }
    catch (Exception iox)
    {
      iox.printStackTrace();
    }
  }
  
}
